package com.wtwd.campus.vcom.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.wtwd.campus.dao.LocationMapper;
import com.wtwd.campus.entity.DeviceSOSList;
import com.wtwd.campus.entity.LocationDataVo;
import com.wtwd.campus.entity.VcomNoticeMessage;
import com.wtwd.campus.service.RedisService;
import com.wtwd.campus.entity.VcomShortMessage;
import com.wtwd.campus.vcom.common.Constant;
import com.wtwd.campus.vcom.common.RequestId;
import com.wtwd.campus.vcom.common.RespCode;
import com.wtwd.campus.vcom.common.ResponseEntity;
import com.wtwd.campus.vcom.dao.VcomDeviceInfoMapper;
import com.wtwd.campus.vcom.dao.VcomPhoneMapper;
import com.wtwd.campus.vcom.entity.VcomNotDisturb;
import com.wtwd.campus.vcom.entity.VcomPhoneData;
import com.wtwd.campus.vcom.entity.VcomRequestRecord;
import com.wtwd.campus.vcom.entity.vo.NotDisturb;
import com.wtwd.campus.vcom.service.RequestRecordService;
import com.wtwd.campus.vcom.service.VcomDeviceInfoService;
import com.wtwd.campus.vcom.utils.CommandSendUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author: ldaoliang
 * @DateTime: 2022/1/5 13:37
 * @Description:
 */
@Service
public class VcomDeviceInfoServiceImpl implements VcomDeviceInfoService {

    private static final Logger logger = LoggerFactory.getLogger(VcomDeviceInfoServiceImpl.class);

    @Autowired
    LocationMapper locationMapper;
    @Autowired
    VcomDeviceInfoMapper vcomDeviceInfoMapper;
    @Autowired
    CommandSendUtils commandSendUtils;
    @Autowired
    private RequestRecordService requestRecordService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private VcomPhoneMapper vcomPhoneMapper;

    @Override
    public LocationDataVo getDeviceLatestLocation(String imei) {
        return locationMapper.getDeviceLastLocationDataByImei(imei);
    }

    /**
     * @param action
     * @param commandValue
     * @param imei
     * @return
     */
    @Override
    @Transactional
    public ResponseEntity setPhoneData(String action, String commandValue, String imei) {
        //根据action获取类型
        int type = getType(action);
        if (type == 0) {
            return new ResponseEntity(RespCode.ACTION_ERROR, false, null);
        }
        //校验数据的正确性（不可重复添加号码）
        int flag = judgeData(commandValue, type);
        if (flag == 1) {
            return new ResponseEntity(RespCode.PHONE_NUMBER_REPEAT, false, null);
        } else if (flag == 2) {
            return new ResponseEntity(RespCode.PHONE_NUMBER_OVER_LIMIT, false, null);
        }
        //保存请求id
        RequestId requestId = requestRecordService.saveRequestRecord(imei, commandValue, type);
        if (!requestId.isSuccess()) {
            return new ResponseEntity(RespCode.REQUEST_DEAL_ERROR, false, null);
        }
        // 判断当前条是否需要发送（该设备该类型是否有未完成的，如果没有则查询是否最老的一条未发送的进行发送）
        VcomRequestRecord nextSendCommand = requestRecordService.getNextSendCommand(imei, requestId.getRequestId(), type);
        if (nextSendCommand == null) {
            return new ResponseEntity(RespCode.WAITING_SEND, true, requestId.getRequestId());
        }
        //设置真正需要下发的指令内容
        commandValue = nextSendCommand.getRequestContent();
        // 根据action的类型分别处理
        switch (action) {
            case "sos":
                JSONArray sosNoArray = JSON.parseArray(commandValue);
                return dealSOS(sosNoArray, nextSendCommand);
            case "familyNo":
                JSONArray familyNoArray = JSON.parseArray(commandValue);
                return dealFamilyNo(familyNoArray, nextSendCommand);
            case "whiteList":
                JSONArray whiteList = JSON.parseArray(commandValue);
                return dealWhiteNo(whiteList, nextSendCommand);
            default:
                return new ResponseEntity(RespCode.ACTION_ERROR, false, null);
        }
    }

    /**
     * 根据action获取type
     *
     * @param action
     * @return
     */
    public int getType(String action) {
        int type = 0;
        switch (action) {
            case "sos":
                type = Constant.COMMAND_TYPE_SOS;
                break;
            case "familyNo":
                type = Constant.COMMAND_TYPE_FAMILY_NO;
                break;
            case "whiteList":
                type = Constant.COMMAND_TYPE_WHITE_LIST;
                break;
            default:
                return type;
        }
        return type;
    }

    /**
     * 判断号码是否重复添加并且校验号码个数是否超过限定
     *
     * @param commandValue
     * @return
     */
    public int judgeData(String commandValue, int type) {
        JSONArray familyNoArray = JSON.parseArray(commandValue);
        List<String> phoneList = new ArrayList<>();
        for (Object o : familyNoArray) {
            JSONObject data = (JSONObject) o;
            String phone = data.getString("phone");
            if (phoneList.contains(phone)) {
                return 1;
            }
            phoneList.add(phone);
        }
        if (type == Constant.PHONE_FAMILY && phoneList.size() > 3) {
            return 2;
        } else if (type == Constant.PHONE_WHITE && phoneList.size() > 17) {
            return 2;
        }
        return 3;
    }


    /**
     * 进行亲情号码的指令下发
     *
     * @param array
     */
    public ResponseEntity dealFamilyNo(JSONArray array, VcomRequestRecord vcomRequestRecord) {
        String imei = vcomRequestRecord.getImei();
        String commandNumber = vcomRequestRecord.getCommandNumber();
        String requestId = vcomRequestRecord.getRequestId();
        //解析数据
        List<Map<String, Object>> list = resolveData(array, 3, 4, 6, Constant.PHONE_FAMILY);
        //修改数据库号码表中的数据
        String currData = JSONObject.toJSONString(list);
        int i = addOrModify(imei, Constant.PHONE_FAMILY, currData, commandNumber);
        if (i > 0) {
            // 发送指令
            boolean b = commandSendUtils.setFamilyNo(list, imei, commandNumber);
            return dealDeviceOffLine(b, imei, requestId);
        } else {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return new ResponseEntity(RespCode.WAITING_SEND, true, requestId);
    }

    /**
     * 进行SOS号码的指令下发
     *
     * @param object
     */
    public ResponseEntity dealSOS(JSONArray object, VcomRequestRecord vcomRequestRecord) {
        String imei = vcomRequestRecord.getImei();
        String commandNumber = vcomRequestRecord.getCommandNumber();
        String requestId = vcomRequestRecord.getRequestId();
        //解析数据
        List<DeviceSOSList> list = new ArrayList<>();
        List<Map<String, Object>> saveData = new ArrayList<>();
        for (int i = 1; i <= 3; i++) {
            DeviceSOSList deviceSOSList = new DeviceSOSList();
            Map<String, Object> save = new HashMap<>();
            String name = "";
            String phone = "";
            if (object.size() >= i) {
                name = object.getJSONObject(i - 1).getString("relationship");
                phone = object.getJSONObject(i - 1).getString("phone");
            }
            deviceSOSList.setSosName(name);
            deviceSOSList.setSosPhone(phone);
            deviceSOSList.setSequence(i);
            list.add(deviceSOSList);
            save.put("name", name);
            save.put("phone", phone);
            save.put("sequence", i);
            saveData.add(save);
        }
        //修改数据库号码表中的数据
        String currData = JSONObject.toJSONString(saveData);
        int i = addOrModify(imei, Constant.PHONE_SOS, currData, commandNumber);
        if (i > 0) {
            // 发送指令
            boolean b = commandSendUtils.setSOS(list, imei, commandNumber);
            return dealDeviceOffLine(b, imei, requestId);
        } else {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return new ResponseEntity(RespCode.WAITING_SEND, true, requestId);
    }

    /**
     * 进行白名单号码的指令下发
     *
     * @param array
     */
    public ResponseEntity dealWhiteNo(JSONArray array, VcomRequestRecord vcomRequestRecord) {
        String imei = vcomRequestRecord.getImei();
        String commandNumber = vcomRequestRecord.getCommandNumber();
        String requestId = vcomRequestRecord.getRequestId();
        //解析数据
        List<Map<String, Object>> list = resolveData(array, 17, 7, 23, Constant.PHONE_WHITE);
        //修改数据库号码表中的数据
        String currData = JSONObject.toJSONString(list);
        int i = addOrModify(imei, Constant.PHONE_WHITE, currData, commandNumber);
        if (i > 0) {
            // 发送指令
            boolean b = commandSendUtils.setWhiteNo(list, imei, commandNumber);
            return dealDeviceOffLine(b, imei, requestId);
        } else {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return new ResponseEntity(RespCode.WAITING_SEND, true, requestId);
    }

    /**
     * 解析白名单和亲情号数据
     *
     * @return
     */
    public List<Map<String, Object>> resolveData(JSONArray array, int size, int start, int end, int type) {
        //解析数据
        List<Map<String, Object>> list = new ArrayList<>();
        List<Integer> seqList = new ArrayList<>();
        int whiteSeq = 7;
        for (Object e : array) {
            JSONObject data = (JSONObject) e;
            Integer seq = 0;
            if (type == Constant.PHONE_WHITE) {
                seq = whiteSeq;
                whiteSeq++;
            } else if (type == Constant.PHONE_FAMILY) {
                seq = data.getInteger("pressKey") + 3;
            }
            String phone = data.getString("phone");
            Map<String, Object> map = new HashMap<>();
            map.put("name", data.getString("relationship"));
            map.put("phone", phone);
            map.put("sequence", seq);
            list.add(map);
            seqList.add(seq);
        }
        //亲情号码不足则补全
        if (list.size() < size) {
            for (int i = start; i <= end; i++) {
                if (!seqList.contains(i)) {
                    Map<String, Object> map = new HashMap<>();
                    map.put("name", "");
                    map.put("phone", "");
                    map.put("sequence", i);
                    list.add(map);
                }
            }
        }
        //判断添加号码个数是否超过限定值
        if (type == Constant.PHONE_WHITE && list.size() > 17) {
            return null;
        } else if (type == Constant.PHONE_FAMILY && list.size() > 3) {
            return null;
        }
        return list;
    }


    /**
     * 修改数据库中信息
     *
     * @param imei
     * @param type
     * @param currData
     * @param commandNumber
     * @return
     */
    public int addOrModify(String imei, Integer type, String currData, String commandNumber) {
        //修改数据库号码表中的数据
        VcomPhoneData phoneData = vcomPhoneMapper.getPhoneListByType(imei, type);
        long time = System.currentTimeMillis();
        int i = 0;
        if (phoneData == null) {
            phoneData = new VcomPhoneData();
            phoneData.setCommandNumber(commandNumber);
            phoneData.setImei(imei);
            phoneData.setPhoneData(currData);
            phoneData.setStatus(Constant.PHONE_STATUS_STAY);
            phoneData.setType(type);
            phoneData.setUpdateTime(time);
            //新增一笔号码数据
            i = vcomPhoneMapper.addPhoneRecord(phoneData);
        } else {
            phoneData.setUpdateTime(time);
            phoneData.setCommandNumber(commandNumber);
            phoneData.setStatus(Constant.PHONE_STATUS_STAY);
            String oldData = phoneData.getPhoneData();
            phoneData.setOldData(oldData);
            phoneData.setPhoneData(currData);
            //修改一笔号码数据
            i = vcomPhoneMapper.modifyPhoneRecord(phoneData);
        }
        return i;
    }

    /**
     * 处理设备是否在线
     *
     * @param b
     * @param imei
     * @param requestId
     * @return
     */
    public ResponseEntity dealDeviceOffLine(boolean b, String imei, String requestId) {
        if (b) {
            if (!commandSendUtils.deviceOnline(imei)) {
                return new ResponseEntity(RespCode.DEVICE_OFF_LINE, true, requestId);
            }
            return new ResponseEntity(RespCode.SUCCESS, true, requestId);
        } else {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new ResponseEntity(RespCode.WAITING_SEND, true, requestId);
        }
    }


    public static void main(String[] args) {
        String a = "[{\"relationship\":\"妈\",\"phone\":\"13439301795\",\"pressKey\":\"1\"},{\"relationship\":\"妈\",\"phone\":\"13439301796\",\"pressKey\":\"2\"}]";
        JSONArray objects = JSON.parseArray(a);
        objects.stream().forEach(e -> {
            JSONObject data = (JSONObject) e;
            System.out.println(data.getString("phone"));

        });
    }

    @Override
    public ResponseEntity useDealFamilyNo(JSONArray array, VcomRequestRecord vcomRequestRecord) {
        return dealFamilyNo(array, vcomRequestRecord);
    }

    @Override
    public ResponseEntity useDealSos(JSONArray object, VcomRequestRecord vcomRequestRecord) {
        return dealSOS(object, vcomRequestRecord);
    }

    @Override
    public List<VcomPhoneData> getPhoneDataByImei(String imei) {
        return vcomPhoneMapper.getPhoneDataByImei(imei);
    }

    @Override
    public boolean factoryDataReset(String imei, String commandNumber) {
        return commandSendUtils.reSetDevice(imei, commandNumber);
    }

    @Override
    public boolean getDeviceOnline(String imei) {
        return commandSendUtils.deviceOnline(imei);
    }

    @Override
    public VcomRequestRecord getInstructionState(String imei, String requestId) {
        return vcomDeviceInfoMapper.getInstructionState(imei,requestId);
    }

    @Override
    public ResponseEntity useDealWhiteNo(JSONArray array, VcomRequestRecord vcomRequestRecord) {
        return dealWhiteNo(array, vcomRequestRecord);
    }

    @Override
    @Transactional
    public ResponseEntity setNotDisturbData(VcomRequestRecord requestRecord) {
        String commandNumber = requestRecord.getCommandNumber();
        String imei = requestRecord.getImei();
        String requestContent = requestRecord.getRequestContent();
        String requestId = requestRecord.getRequestId();
        // 解析里面的数据
        JSONObject jsonObject = JSON.parseObject(requestContent);
        JSONArray notDisturbArray = jsonObject.getJSONObject("item").getJSONArray("notDisturb");
        String notDisturbString = notDisturbArray.toJSONString();
        List<NotDisturb> notDisturbList = JSONArray.parseArray(notDisturbString, NotDisturb.class);
        Map<Integer, List<NotDisturb>> notDisturbMap = notDisturbList.stream()
                .collect(Collectors.groupingBy(NotDisturb::getWeekdays));
        // 判断数据库是否有该设备数据，没有则添加
        VcomNotDisturb vcomNotDisturbByImei = vcomDeviceInfoMapper.getVcomNotDisturbByImei(imei);
        int dataBaseResult = 0;
        if (vcomNotDisturbByImei == null) {
            dataBaseResult = vcomDeviceInfoMapper.addVcomNotDisturb(imei, requestContent, commandNumber, Constant.WAITING_EFFECT);
        } else {
            dataBaseResult = vcomDeviceInfoMapper.updateVcomNotDisturb(imei, requestContent, commandNumber, Constant.WAITING_EFFECT);
        }
        if (dataBaseResult > 0) {
            // 发送指令
            boolean b = commandSendUtils.sendNotDisturb(imei, notDisturbMap, commandNumber);
            logger.info("免打扰指令下发结果：result={},commandNumber={}", b, requestRecord.getCommandNumber());
            if (b) {
                if (!commandSendUtils.deviceOnline(imei)) {
                    return new ResponseEntity(RespCode.DEVICE_OFF_LINE, true, requestId);
                }
                return new ResponseEntity(RespCode.SUCCESS, true, requestId);
            } else {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return new ResponseEntity(RespCode.WAITING_SEND, true, requestId);
            }
        } else {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return new ResponseEntity(RespCode.WAITING_SEND, true, requestId);
    }

    @Override
    public boolean dealNotDisturbReply(String imei, String commandNumber) {
        VcomNotDisturb vcomNotDisturb = vcomDeviceInfoMapper.getVcomNotDisturbByImei(imei);
        if (vcomNotDisturb != null) {
            // 如果序列号一样且待生效状态，则做对应的操作
            if (commandNumber.equals(vcomNotDisturb.getCommandNumber()) && vcomNotDisturb.getStatus() == Constant.WAITING_EFFECT) {
                int i = vcomDeviceInfoMapper.completeNotDisturb(imei);
                return i > 0;
            }
        }
        return true;
    }

    @Override
    public boolean dealFailedDotDisturb(String imei, String commandNumber) {
        VcomNotDisturb vcomNotDisturb = vcomDeviceInfoMapper.getVcomNotDisturbByImei(imei);
        if (vcomNotDisturb != null) {
            // 如果序列号一样且待生效状态，则做对应的操作
            if (commandNumber.equals(vcomNotDisturb.getCommandNumber()) && vcomNotDisturb.getStatus() == Constant.WAITING_EFFECT) {
                int i = vcomDeviceInfoMapper.completeFailedNotDisturb(imei);
                return i > 0;
            }
        }
        return true;
    }

    @Override
    public ResponseEntity sendMessage(VcomRequestRecord requestRecord) {
        String commandNumber = requestRecord.getCommandNumber();
        String imei = requestRecord.getImei();
        String requestContent = requestRecord.getRequestContent();
        String requestId = requestRecord.getRequestId();
        VcomNoticeMessage noticeMessage = JSONObject.parseObject(requestContent, VcomNoticeMessage.class);
        boolean b = commandSendUtils.deviceOnline(imei);
        boolean sendResult = commandSendUtils.sendNoticeMessage(imei, commandNumber, noticeMessage);
        if (!b) {
            return new ResponseEntity(RespCode.DEVICE_OFF_LINE, true, requestId);
        }
        if (sendResult) {
            return new ResponseEntity(RespCode.SUCCESS, true, requestId);
        }
        return new ResponseEntity(RespCode.WAITING_SEND, true, requestId);
    }

    @Override
    public ResponseEntity sendShortMessage(VcomRequestRecord requestRecord) {
        String commandNumber = requestRecord.getCommandNumber();
        String imei = requestRecord.getImei();
        String requestContent = requestRecord.getRequestContent();
        String requestId = requestRecord.getRequestId();
        VcomShortMessage shortMessage = JSONObject.parseObject(requestContent, VcomShortMessage.class);
        boolean sendResult = commandSendUtils.sendShortMessage(imei, commandNumber, shortMessage);
        boolean b = commandSendUtils.deviceOnline(imei);
        if (!b) {
            return new ResponseEntity(RespCode.DEVICE_OFF_LINE, true, requestId);
        }
        if (sendResult) {
            return new ResponseEntity(RespCode.SUCCESS, true, requestId);
        }
        return new ResponseEntity(RespCode.WAITING_SEND, true, requestId);
    }
}
